import { createElement, HTMLAttributes, isValidElement, ReactElement, useEffect, useState, type FC } from 'react';
import { createPortal } from 'react-dom';
import { CSSObject, jsx } from '@emotion/react';
import classNames from 'classnames';
import { isFragment } from 'react-is';
import { dimmerDefaultProps } from './defaultProps';
import type { DimmerOptions } from './type';
import { useUpdateEffect } from 'react-use';

export interface DimmerProps
  extends DimmerOptions,
    Omit<HTMLAttributes<HTMLDivElement>, 'onMouseEnter' | 'onMouseLeave'> {}

const Dimmer: FC<DimmerProps> = (props) => {
  const {
    className,
    ui,
    dimmable,
    active,
    disabled,
    blurring,
    duration,
    inverted,
    aligned,
    page,
    simple,
    shades,
    partially,
    transition,
    contentWapper,
    children,
    forwardedRef,
    onMouseEnter,
    onMouseLeave,
    ...dimmerProps
  } = props;
  const [actived, setActived] = useState(active);
  const [css, setCss] = useState<string>();
  const [styles, setStyles] = useState<CSSObject>();

  useUpdateEffect(() => {
    if (!disabled) {
      if (active) {
        setActived(true);
        setCss(classNames('transition', 'animating', transition, 'in'));
        setStyles({ '.ui.dimmer&': { display: 'flex !important', animationDuration: `${duration}ms` } });
        setTimeout(() => {
          setCss('transition visible');
          setStyles({ '.ui.dimmer&': { display: 'flex !important' } });
        }, duration);
      } else {
        setCss(classNames('transition', 'visible', 'animating', transition, 'out'));
        setStyles({ '.ui.dimmer&': { display: 'flex !important', animationDuration: `${duration}ms` } });
        setTimeout(() => {
          setCss('transition hidden');
          setStyles({ '.ui.dimmer&': { display: 'none' } });
          setActived(false);
        }, duration);
      }
    }
  }, [active, disabled]);

  useEffect(() => {
    if (page) {
      const tokens: Array<string> = [];
      tokens.push('dimmable', 'dimmed');
      if (blurring) {
        tokens.push('blurring');
      }
      if (actived) {
        document.body.classList.add(...tokens);
      } else {
        document.body.classList.remove(...tokens);
      }
    }
  }, [actived]);

  const dimme = jsx(
    'div',
    {
      key: 'dimmer',
      ref: forwardedRef,
      className: classNames(
        { ui, page, active: actived, disabled, inverted },
        aligned,
        { aligned, simple },
        shades,
        partially,
        'dimmer',
        css,
        className,
      ),
      css: styles,
      ...dimmerProps,
    },
    children && (contentWapper ? <div className="content">{children}</div> : children),
  );

  if (page) {
    return createPortal(dimme, document.body);
  } else if (isValidElement(dimmable) && !isFragment(dimmable)) {
    const node = dimmable as ReactElement;

    return createElement(
      node.type,
      {
        ...node.props,
        className: classNames(node.props.className, {
          dimmable: actived || simple,
          dimmed: actived || simple,
          blurring,
        }),
        onMouseEnter,
        onMouseLeave,
      },
      [node.props.children, dimme],
    );
  }
  return null;
};

Dimmer.displayName = 'Dimmer';
Dimmer.defaultProps = dimmerDefaultProps;

export default Dimmer;
